package com.ruijie.acl.service;

import java.util.ArrayList;
import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.springframework.util.Assert;

import com.ruijie.acl.AccessGroup;
import com.ruijie.acl.Ace;
import com.ruijie.acl.AclDevice;
import com.ruijie.acl.AclDeviceTimeRange;
import com.ruijie.acl.TimeRange;
import com.ruijie.emp.device.Device;
import com.ruijie.emp.system.role.internal.UserRoleUtil;
import com.ruijie.emp.system.role.type.PurviewEnum;
import com.ruijie.foundation.dao.support.Page;
import com.ruijie.foundation.exception.BusinessException;

/**
 * <p>
 * Title: ACL设备与ACL时间段关联的服务接口类
 * </p>
 * <p>
 * Description: 为ACL组和ACL时间段关联关系提供逻辑处理，以及数据库的操作。
 * </p>
 * <p>
 * Copyright: Copyright (c) 2008
 * </p>
 * <p>
 * Company: Ruijie Co., Ltd.
 * </p>
 * <p>
 * Create Time: 2009-07-15
 * </p>
 * <p>
 * Update Time:
 * </p>
 * <p>
 * Updater:
 * </p>
 * <p>
 * Update Comments:
 * </p>
 * 
 * @author ASAI
 */
public class DeviceTimeRangeServiceImpl extends AclHibernateEntityExtendDao<AclDeviceTimeRange>
		implements DeviceTimeRangeService {

	/**
	 * 根据ACL设备分页查询ACL时间段
	 * 
	 * @param entity
	 *            ACL设备
	 * @param pageNo
	 *            页数
	 * @param pageSize
	 *            每面显示的记录数
	 * @return ACL时间段
	 */
	@Override
	public Page pagedQueryByDevcie(AclDevice entity, int pageNo, int pageSize) {
		Assert.notNull(entity);
		Criteria criteria = createCriteria(AclDeviceTimeRange.class);
		criteria.add(Restrictions.eq("aclDevice", entity));
		criteria.addOrder(org.hibernate.criterion.Order.asc("timeRange.id"));
		return pagedQuery(criteria, pageNo, pageSize);
	}

	/**
	 * 根据ACL时间段分页查询ACL设备
	 * 
	 * @param timeRange
	 *            ACL时间段
	 * @param pageNo
	 *            页数
	 * @param pageSize
	 *            每面显示的记录数
	 * @return ACL设备
	 */
	public Page pagedQueryByTimeRange(TimeRange entity, int pageNo, int pageSize) {
		Assert.notNull(entity);
		Criteria criteria = createCriteria(AclDeviceTimeRange.class);
		criteria.add(Restrictions.eq("timeRange", entity));
		
		//-------------------------add by sinyee -----------------------------------
		criteria.createCriteria("aclDevice","ad").add(Restrictions.sqlRestriction(UserRoleUtil.getSQLNoAnd("ad1_", "device_id")));
		
		return pagedQuery(criteria, pageNo, pageSize);
	}

	/**
	 * 是否存在时间段与设备的关联
	 * 
	 * @param aclDevice
	 *            设备
	 * @param timeRange
	 *            时间段
	 * @return
	 */
	public boolean isExistDeviceTimeRange(AclDevice aclDevice, TimeRange timeRange) {
		if (aclDevice == null && timeRange == null) {
			return false;
		} else {
			Criteria criteria = createCriteria(AclDeviceTimeRange.class);
			if (aclDevice != null) {
				criteria.add(Restrictions.eq("aclDevice.id", aclDevice.getId()));
			}
			if (timeRange != null) {
				criteria.add(Restrictions.eq("timeRange.id", timeRange.getId()));
			}
			int totalCount = (Integer) criteria.setProjection(Projections.rowCount())
					.uniqueResult();

			// 如果都没有被使用,返回False
			if (totalCount == 0) {
				return false;
			} else {
				return true;
			}
		}
	}

	/**
	 * 根据ACL设备和时间段取得关系对象
	 * 
	 * @param aclDevice
	 *            ACL设备
	 * @param timeRange
	 *            时间段
	 * @return 关系对象
	 */
	@SuppressWarnings("unchecked")
	public AclDeviceTimeRange getByAclDeviceAndTimeRange(AclDevice aclDevice, TimeRange timeRange) {
		Assert.notNull(aclDevice);
		Assert.notNull(timeRange);
		AclDeviceTimeRange result = null;
		Criteria criteria = createCriteria(AclDeviceTimeRange.class);
		criteria.add(Restrictions.eq("aclDevice", aclDevice));
		criteria.add(Restrictions.eq("timeRange", timeRange));
		List<AclDeviceTimeRange> list = (List<AclDeviceTimeRange>) criteria.list();
		if (list != null && list.size() > 0) {
			result = list.get(0);
		}
		return result;
	}

	/**
	 * 根据ACL设备删除ACL设备与时间段关系
	 * 
	 * @param aclDevice
	 *            ACL设备
	 */
	public void deleteByAclDevice(AclDevice aclDevice) {
		String hql = "delete from AclDeviceTimeRange where aclDevice=?";
		this.createQuery(hql, aclDevice).executeUpdate();
	}

	/**
	 * 根据时间段判断是否存在修改标志位为已修改的ACL设备与时间段关系
	 * 
	 * @param entity
	 *            时间段
	 * @return 是否存在ACL设备与时间段关系
	 */
	public boolean existByTimeRangeAndChanged(TimeRange entity) {
		Assert.notNull(entity);
		Criteria criteria = createCriteria(AclDeviceTimeRange.class);
		criteria.add(Restrictions.eq("timeRange", entity));
		criteria.add(Restrictions.eq("isChanged", true));
		int count = (Integer) criteria.setProjection(Projections.rowCount()).uniqueResult();
		return count > 0;
	}

	/**
	 * 取得有变更的ACL设备列表
	 * 
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public List<AclDeviceTimeRange> getAclDeviceByChanged(TimeRange entity) {
		Criteria criteria = createCriteria(AclDeviceTimeRange.class);
		criteria.add(Restrictions.eq("timeRange", entity));
		criteria.add(Restrictions.eq("isChanged", true));
		return criteria.list();
	}

	/**
	 * 根据时间段更新关系的修改标志位
	 * 
	 * @param entity
	 *            时间段
	 */
	public void updateChangedByTimeRange(TimeRange entity) {
		String hql = "update AclDeviceTimeRange set isChanged = ? where timeRange = ?";
		this.createQuery(hql, entity.getIsChanged(), entity).executeUpdate();
	}
	
	/**
	 * 根据时间段更新关系的修改标志位
	 * 
	 * @param entity
	 *            时间段
	 */
	public void updateChangedByTimeRange(TimeRange entity,boolean isChanged,AclDevice aclDevice) {
		String hql = "update AclDeviceTimeRange set isChanged = ? where timeRange = ? and aclDevice=?";
		this.createQuery(hql, isChanged, entity,aclDevice).executeUpdate();
	}
	

	/**
	 * 根据ACL时间段删除ACL设备与ACL时间段关系
	 * 
	 * @param accessGroup
	 *            ACL组
	 */
	public void deleteByTimeRange(String timeRangeid, String deiveid) {
		String hql = "delete from AclDeviceTimeRange where aclDevice.id=" + deiveid
				+ " and  timeRange.id in (" + timeRangeid + ")";
		this.createQuery(hql).executeUpdate();
	}

	/**
	 * 添加设备与ACL时间段关系
	 * 
	 * @param accessGroupList
	 *            ACL时间段列表
	 * @param device
	 *            设备
	 */
	public void addTimeRangeDevices(List<TimeRange> timeRangeList, Device device) {
		Assert.notNull(device);
		// 取得Acl Device
		AclDevice aclDevice = this.findUniqueBy(AclDevice.class, "device", device);
		// 如果不是Acl Device
		if (aclDevice == null) {
			// 该设备不是ACL设备，无法与ACL时间段创建关联
			throw new BusinessException("acl_device_timerange_error_no_acldevice");
		}
		if (timeRangeList != null && timeRangeList.size() > 0) {
			for (TimeRange timeRange : timeRangeList) {
				if (timeRange != null && timeRange.getAclDevice() == null) {
					try {
						this.refresh(timeRange);
					} catch (Exception ex) {
						return;
					}
					AclDeviceTimeRange entity = this.getByAclDeviceAndTimeRange(aclDevice,
							timeRange);
					if (entity == null) {
						// 不存在此ACL时间段与ACL设备关联时,新建一个
						entity = new AclDeviceTimeRange();
						entity.setAclDevice(aclDevice);
						entity.setTimeRange(timeRange);
						this.save(entity);
					} else {
						// 若存在,且其修改标志为不一致时,修改其修改标志位
						if (entity.getIsChanged()) {
							entity.setIsChanged(false);
							this.update(entity);
						}
					}
				}
			}
		}
	}

	/**
	 * 通过ACL组和acl设备保存deviceTimeRangeService
	 * 
	 * @param accessGroup
	 * @param aclDevice
	 */
	public void saveAclDeviceTimeRange(AccessGroup accessGroup, Device device) {
		List<Ace> aceList = accessGroup.getAces();
		List<TimeRange> timeRangeList = new ArrayList<TimeRange>();
		if (aceList != null && aceList.size() > 0) {
			for (Ace ace : aceList) {
				if (ace != null && ace.getTimeRange() != null) {
					timeRangeList.add(ace.getTimeRange());
				}
			}
		}
		if (timeRangeList != null && timeRangeList.size() > 0) {
			addTimeRangeDevices(timeRangeList, device);
		}
	}

	/**
	 * 根据ACL设备取得所有ACL设备与时间段关系
	 * 
	 * @param entity
	 *            ACL设备
	 * @return ACL设备与时间段关系
	 */
	@SuppressWarnings("unchecked")
	public List<AclDeviceTimeRange> getByAclDevice(AclDevice entity) {
		Assert.notNull(entity);
		Criteria criteria = createCriteria(AclDeviceTimeRange.class);
		criteria.add(Restrictions.eq("aclDevice", entity));
		return (List<AclDeviceTimeRange>) criteria.list();
	}

	/**
	 * 根据ACL设备取得时间段
	 * 
	 * @param entity
	 *            ACL设备
	 * @return 时间段列表
	 */
	public List<TimeRange> getTimeRangeByAclDevice(AclDevice entity) {
		List<TimeRange> list = new ArrayList<TimeRange>();
		List<AclDeviceTimeRange> aclDeviceTimeRangeList = getByAclDevice(entity);
		if (aclDeviceTimeRangeList != null && aclDeviceTimeRangeList.size() > 0) {
			for (AclDeviceTimeRange aclDeviceTimeRange : aclDeviceTimeRangeList) {
				list.add(aclDeviceTimeRange.getTimeRange());
			}
		}
		return list;
	}
}
